package com.springboot.service;

import com.springboot.constant.CommonConstant;
import com.springboot.domain.BtFile;
import com.springboot.domain.Result;
import com.springboot.dto.updto.ControllerResponse;
import com.springboot.enums.ResultEnum;
import com.springboot.exception.StorageException;
import com.springboot.exception.StorageFileNotFoundException;
import com.springboot.repository.FileRepository;
import com.springboot.tools.ResultUtil;
import com.springboot.tools.UUIDTool;
import com.springboot.uploadDir.StorageProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.stereotype.Service;
import org.springframework.util.FileSystemUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.stream.Stream;

@Slf4j
@Service
public class FileSystemStorageService {

    private final Path rootLocation;
    private final Path rootFileLocation;
    private FileRepository fileRepository;
    private File file;
    private String downloadSaveFileName;

    @Autowired
    public FileSystemStorageService(StorageProperties properties, FileRepository fileRepository) {
        this.rootLocation = Paths.get(properties.getLocation());
        this.rootFileLocation = Paths.get(properties.getFilelocation());
        this.fileRepository = fileRepository;
    }

//
//    public ControllerResponse store(MultipartFile file, HttpSession session) {
//        try {
//            String a = session.getAttribute("uuid").toString();
//        } catch (NullPointerException e) {
//            log.info("请先登录!" + e.toString());
//            return ControllerResponse.create("请先登录!", false);
//        }
//        ControllerResponse checkFormatResponse = checkFormat(file);
//        if (!checkFormatResponse.getABoolean()) {
//            return checkFormatResponse;
//        }
//        if (getFormatName(file)) {
//        } else {
//            log.info("Maybe not a picture file!");
//            return ControllerResponse.create("Maybe not a picture file!", false);
//        }
//        ControllerResponse copyResponse = copyPicture(file);
//        if (copyResponse.getABoolean()) {
//            return copyResponse;
//        }
//
//        ControllerResponse renamePictureResponse = renamePicture(file);
//        if (renamePictureResponse.getABoolean()) {
//            return renamePictureResponse;
//        }
//        String name = uploadMapper.findFile(session.getAttribute("uuid").toString()).getPictureName();
//        if (name != null) {
//            deleteFile(loadPicture(name));
//        }
//        ControllerResponse updatePictureResponse = updatePicture(renamePictureResponse.getMessage());
//        return updatePictureResponse;
//    }


    public Result storeFile(MultipartFile file, String parameterName, HttpSession session, boolean isTemplate) {
        if (null == session.getAttribute("user")) {
            return ResultUtil.error(ResultEnum.NOT_LOGIN);
        }
        Result result= checkPicture(file,parameterName,session);
        if (!result.getABoolean()){
            return result;
        }
        Result checkFormatResponse = checkFormat(file);
        if (!checkFormatResponse.getABoolean()) {
            return checkFormatResponse;
        }
        Result copyResponse = copyFile(file);
        if (!copyResponse.getABoolean()) {
            return copyResponse;
        }
        String temName = UUIDTool.getUuid() + file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
        Result renameFileResponse = renameFile(file, temName);
        if (!renameFileResponse.getABoolean()) {
            return renameFileResponse;
        }
        BtFile btfile = new BtFile();
        btfile.setOriginalFileName(file.getOriginalFilename());
        btfile.setContentType(file.getContentType());
        btfile.setCreateTime(new Date());
        btfile.setFileName(temName);
        btfile.setEffective(CommonConstant.EFFECTIVE);
        if (isTemplate) {
            btfile.setUserId((String) session.getAttribute("user"));
        }
        btfile.setId(UUIDTool.getUuid());
        btfile.setParameterName(parameterName);
        fileRepository.save(btfile);
        Map<String, String> fileId = new HashMap<>();
        fileId.put("fileId", btfile.getId());
        return ResultUtil.success(fileId);
    }

    public ControllerResponse renamePicture(MultipartFile file) {
        String temName = UUIDTool.getUuid() + file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
        File oldPicture = new File("upload-dir" + File.separator + "picture" + File.separator + file.getOriginalFilename());
        File newPicture = new File("upload-dir" + File.separator + "picture" + File.separator + temName);
        try {
            boolean flag = oldPicture.renameTo(newPicture);
            if (flag) {
            } else {
                log.info("RenameToPicture faild！");
                return ControllerResponse.create("RenameToPicture faild！", true);
            }
        } catch (SecurityException e) {
            log.info("RenameToPicture faild！");
            return ControllerResponse.create("RenameToPicture faild！", true);
        }
        return ControllerResponse.create(temName, false);
    }

    public Result renameFile(MultipartFile file, String temName) {

        File oldFile = new File("upload-dir" + File.separator + "file" + File.separator + file.getOriginalFilename());
        File newFile = new File("upload-dir" + File.separator + "file" + File.separator + temName);
        try {
            boolean flag = oldFile.renameTo(newFile);
            if (flag) {
            } else {
                log.info("RenameToFile faild！");
                return ResultUtil.error(ResultEnum.RENAME_FILE);
            }
        } catch (SecurityException e) {
            log.info("RenameToFile faild！");
            return ResultUtil.error(ResultEnum.RENAME_FILE);
        }
        return ResultUtil.success(ResultEnum.SUCCESS);
    }

    public ControllerResponse copyPicture(MultipartFile file) {
        try {
            Files.copy(file.getInputStream(), this.rootLocation.resolve(file.getOriginalFilename()));
        } catch (FileAlreadyExistsException e) {
            log.info("Picture already exist！");
            return ControllerResponse.create("Picture already exist！", true);
        } catch (IOException e) {
            log.info("Storage file failed！");
            return ControllerResponse.create("Storage file failed！ ", true);
        }
        log.info("success");
        return ControllerResponse.create("success", false);
    }

    public Result copyFile(MultipartFile file) {
        try {
            Files.copy(file.getInputStream(), this.rootFileLocation.resolve(file.getOriginalFilename()));
        } catch (FileAlreadyExistsException e) {
            log.info("File already exist！");
            return ResultUtil.error(ResultEnum.FILE_EXIST);
        } catch (IOException e) {
            log.info("Storage file failed！");
            return ResultUtil.error(ResultEnum.STORAGE_FAIED);
        }
        log.info("success");
        return ResultUtil.success(ResultEnum.SUCCESS);
    }

    public Result checkFormat(MultipartFile file) {
        try {
            if (file.isEmpty()) {
                log.info("文件(内容)为空！");
                return ResultUtil.error(ResultEnum.EMPTY_FILE);
            }
        } catch (StringIndexOutOfBoundsException e) {
            log.info("文件格式有误！");
            return ResultUtil.error(ResultEnum.ERROR_FORMAT);
        }
        log.info("success");
        return ResultUtil.success(ResultEnum.SUCCESS);
    }


    public Path loadPicture(String pictureName) {
        return rootLocation.resolve(pictureName);
    }


    public Path loadFile(String fileName) {
        return rootFileLocation.resolve(fileName);
    }


    public Resource loadAsResource(String filename) {
        try {
            Path file = loadPicture(filename);
            Resource resource = new UrlResource(file.toUri());
            if (resource.exists() || resource.isReadable()) {
                return resource;
            } else {
                log.info("Could not read picture: " + filename);
                throw new StorageFileNotFoundException("Could not read picture: " + filename);
            }
        } catch (MalformedURLException e) {
            log.info("Could not read picture:" + filename);
            throw new StorageFileNotFoundException("Could not read picture: " + filename, e);
        }

    }


    public Resource loadAsResourceFile(BtFile orifile) throws IOException {
        String filename = orifile.getFileName();
        String orifilename = orifile.getOriginalFileName();
        orifile.setFileName(orifilename);
        try {
            Path file = loadFile(filename);
            Resource resource = new UrlResource(file.toUri());
            if (resource.exists() || resource.isReadable()) {
                BeanUtils.copyProperties(orifile, resource.getFile());
                return resource;
            } else {
                log.info("Could not read file: " + orifilename);
                throw new StorageFileNotFoundException("Could not read file: " + orifilename);
            }
        } catch (MalformedURLException e) {
            log.info("Could not read file: " + orifilename);
            throw new StorageFileNotFoundException("Could not read file: " + orifilename, e);
        }

    }


    public void deleteAll() {
        FileSystemUtils.deleteRecursively(rootLocation.toFile());
        FileSystemUtils.deleteRecursively(rootFileLocation.toFile());
    }

    public void deleteFile(Path path) {
        try {
            Files.delete(path);
        } catch (IOException e) {
            log.info(e.getMessage());
        }
    }


    public void init() {
        try {
            Files.createDirectory(rootLocation);
            Files.createDirectory(rootFileLocation);
        } catch (IOException e) {
            log.info("初始化存储失败！");
            throw new StorageException("初始化存储失败！", e);
        }
    }

    public boolean imageFormat(MultipartFile file) {
        try {
            ImageInputStream iis = ImageIO.createImageInputStream(file.getInputStream());
            Iterator<ImageReader> iterator = ImageIO.getImageReaders(iis);
            if (iterator.hasNext()) {
                return true;
            } else {
                iis.close();
                return false;
            }
        } catch (IllegalArgumentException e) {
            return false;
        } catch (IOException e) {
            return false;
        }
    }


    public Stream<Path> loadAll() {
        try {
            return Files.walk(this.rootLocation, 1)
                    .filter(path -> !path.equals(this.rootLocation))
                    .map(path -> this.rootLocation.relativize(path));
        } catch (IOException e) {
            log.info("Failed to read the stored file！");
            throw new StorageException("Failed to read the stored file！", e);
        }
    }

    public void renameFile(String fileName, String downloadSaveFileName) {
        if (null == fileName && "".equals(fileName)) {
            throw new IllegalArgumentException("fileName can not be blank.");
        }
        if (null == downloadSaveFileName && "".equals(downloadSaveFileName)) {
            throw new IllegalArgumentException("downloadSaveFileName can not be blank.");
        }

        String fullFileName = fileName.trim();
//        if (fileName.startsWith("/") || fileName.startsWith("\\")) {
//            if (baseDownloadPath.equals("/")) {
//                fullFileName = fileName;
//            } else {
//                fullFileName = baseDownloadPath + fileName;
//            }
//        } else {
//            fullFileName = baseDownloadPath + File.separator + fileName;
//        }

        this.file = new File(fullFileName);
        this.downloadSaveFileName = downloadSaveFileName;
    }

    public Result checkPicture(MultipartFile file,String parameterName,HttpSession session){
        String uerId = session.getAttribute("user").toString();
        if (parameterName != null) {
            if (parameterName.equals("headPicture")) {
                if (!imageFormat(file)) {
                    return ResultUtil.error("上传的文件不是图片格式！");
                }
                BtFile headPicture = fileRepository.findFile(uerId, "headPicture");
                if (headPicture != null) {
                    deleteFile(loadFile(headPicture.getFileName()));
                    fileRepository.delete(headPicture.getId());
                }
            }
        }
        return ResultUtil.success();
    }
}
